// 为了更方便直观的修改，将路由定义提前
import 'package:xbaistack/home_page.dart';
import 'package:xbaistack/page/clip_assert_img.dart';
import 'package:xbaistack/page/clip_img.dart';
import 'package:xbaistack/page/customer_keyword_page.dart';
import 'package:xbaistack/page/demo.dart';
import 'package:xbaistack/page/example_page.dart';
import 'package:xbaistack/page/form_page.dart';
import 'package:xbaistack/page/icon_page.dart';
import 'package:xbaistack/page/maodian_page.dart';
import 'package:xbaistack/page/my.dart';
import 'package:xbaistack/page/neet_page.dart';
import 'package:xbaistack/page/picker_page.dart';
import 'package:xbaistack/page/pubbu_page.dart';
import 'package:xbaistack/page/refresh_demo.dart';
import 'package:xbaistack/page/select_langue.dart';
import 'package:xbaistack/page/select_page.dart';
import 'package:xbaistack/page/setting_theme.dart';
import 'package:xbaistack/page/settings_page.dart';
import 'package:xbaistack/page/tabbar_page/tabbar_page.dart';
import 'package:xbaistack/page/text_page.dart';
import 'package:xbaistack/page/tools.dart';
import 'package:xbaistack/page/tost_page.dart';
import 'package:xbaistack/page/webview_page.dart';
import 'package:xbaistack/utils/helper.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:xbaistack/widget/gallery_view_page.dart';
import 'package:xbaistack/widget/picture_view_page.dart';

import 'page/click_page.dart';
import 'page/swiper_page.dart';

const Type _HOME_ = BottomMenuBarPage;
final _routes = Helper.routeDefine({
  _HOME_: (_) => BottomMenuBarPage(),
  DemoPage: (_) => DemoPage(),
  TabbarPage: (_) => TabbarPage(),
  ToolsPage: (_) => ToolsPage(),
  IconPage: (_) => IconPage(),
  SettingsPage: (_) => SettingsPage(),
  NetPage: (_) => NetPage(),
  SelectLanguePage: (_) => SelectLanguePage(),
  MyPage: (_) => MyPage(),
  SettingThemePage: (_) => SettingThemePage(),
  RefreshDemoPage: (_) => RefreshDemoPage(),
  PubuPage: (_) => PubuPage(),
  PictureViewPage: (_) => PictureViewPage(),
  GalleryViewPage: (_) => GalleryViewPage(),
  ToastPage: (_) => ToastPage(),
  SwiperPage: (_) => SwiperPage(),
  ClickPage: (_) => ClickPage(),
  SelectPage: (_) => SelectPage(),
  PickerPage: (_) => PickerPage(),
  CustomizeKeyboard: (_) => CustomizeKeyboard(),
  MyNavigatorPage: (_) => MyNavigatorPage(),
  ClipImgPage: (_) => ClipImgPage(),
  ClipAssetImgPage: (_) => ClipAssetImgPage(),
  TextPage: (_) => TextPage(),
  WebViewPage:(_) => WebViewPage(),
  FormPage:(_) => FormPage(),
  // ExamplePage: (_) => ExamplePage(),
});



/// 这里我们需要将路由管理类改造成单例模式
class MyRouter {
  // 设置成私有构造，
  MyRouter._();

  // 临时变量用于保存路由参数
  // -------------------------
  Object? _arguments;
  String? _routeName;
  BuildContext? _context;
  // -------------------------

  /// 路由定义
  static final ROUTES = _routes;

  /// 单实例对象
  static final MyRouter _instance = MyRouter._();

  /// 对外部公开首页的路由名
  static final String INDEX = Helper.typeName(_HOME_);

  /// 重置临时变量
  void _resetVariables() {
    _context = null;
    _arguments = null;
    _routeName = null;
  }

  /// 携带参数跳转
  Future<T?> to<T extends Object?>() {
    assert(_context != null);
    assert(_routeName != null);
    return Navigator.pushNamed<T>(
      _context!,
      _routeName!,
      arguments: _arguments,
      // 这里当整个流程终结时需要重置临时变量，以节省内存空间。
    ).whenComplete(_resetVariables);
  }

  /// 静态设置参数，这个方法主要是用于在路由跳转时调用
  /// 然后通过上面设置的临时变量进行保存，最后调用 to 时传递过去
  static MyRouter _withArguments(dynamic arguments) {
    _instance._arguments = arguments;
    return _instance;
  }

  /// 这里就是确定路由参数的核心
  /// 由于定义路由时是通过：(_) => Page() 这种方式；
  /// 所以这里可以利用这种规则，我们先对这个函数调用一次，这样的话可以获取到对应页面的实例对象；
  /// 因为页面在混入 RouterBridge 类时就已经确定好了参数类型，所以我们这里我们直接返回
  /// 具体的页面实例对象，就可以调用 RouterBridge 混入类中的 arguments 方法，
  /// 而当我们调用 arguments 方法时，内部又是返回的 MyRouter 单例对象，所以就将外部设置的
  /// 参数又传回来了，然后保存到上面声明的临时变量中。
  static RT of<RT extends RouterBridge>(BuildContext context) {
    assert(
      RT != RouterBridge<dynamic>,
      "You must specify the route type, for example: of<Page>(context)",
    );
    final name = Helper.typeName(RT);
    _instance._context = context; // 临时保存 context
    _instance._routeName = name; // 临时保存路由名
    var builder = ROUTES[name]!; // 取得 WidgetBuilder 对象
    // 这里调用一次就可以获得对应的页面实例对象
    // 既然获得了实例对象，上面的页面又混入了对应的 RouterBridge，在后续调用 arguments 方法时
    // 就能唯一的确定具体路由需要的参数类型
    return builder.call(context) as RT;
  }

  /// 不带任何参数的路由跳转
  static Future<T?> routeTo<T extends Object?>(
    BuildContext context,
    Type router,
  ) {
    final name = Helper.typeName(router); // 将传入的 Type 转换成字符串
    return Navigator.pushNamed<T>(context, name);
  }

  // 这个是在 MaterialApp 定义路由中需要使用的
  static CupertinoPageRoute onGenerateRoute<T>(RouteSettings settings) {
    // print('3131');
    final builder = ROUTES[settings.name] ?? _routes[INDEX]!;
    return CupertinoPageRoute<T>(builder: builder, settings: settings);
  }
}

// 混入类一定要放在和 MyRouter 同一级，这样才可以隐藏 MyRouter._withArguments 的实现
// 避免对外部暴露不需要的方法
mixin RouterBridge<RT_ARG_TYPE> {
  /// 用于设置理由参数
  MyRouter arguments(RT_ARG_TYPE args) => MyRouter._withArguments(args);

  /// 用于还原路由参数到具体的数据类型上
  /// 这样在页面中就可以调用这个方法获取具体的参数类型了
  RT_ARG_TYPE? argumentOf(BuildContext context) {
    final Object? arguments = ModalRoute.of(context)?.settings.arguments;
    return arguments == null ? null : arguments as RT_ARG_TYPE;
  }
}
